package com.ctshk.sapp.airexpress.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ctshk.common.annotations.OperationLogAnnotation;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.OperationLogModel;
import com.ctshk.common.enums.OperationLogType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.utils.Assert;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.individual.scenic.*;
import com.ctshk.common.utils.individual.scenic.dto.ProductIncreaseStrategyDTO;
import com.ctshk.common.utils.individual.scenic.req.ProductIncreaseStrategyBatchReq;
import com.ctshk.common.utils.individual.scenic.req.ProductIncreaseStrategyReq;
import com.ctshk.common.web.support.BaseController;
import com.ctshk.rpc.airexpress.dto.AirportExpressIncreaseStrategyDTO;
import com.ctshk.rpc.airexpress.req.*;
import com.ctshk.rpc.airexpress.service.IAirportExpressIncreaseStrategyService;
import com.ctshk.sapp.airexpress.convertor.Convertor;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;

import javax.validation.*;
import javax.validation.groups.Default;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品加幅策略表 前端控制器
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-02-05
 */
@Slf4j
@RestController
@RequestMapping("/airport/express/increase/strategy")
@Api(value = "机场快线加幅策略", tags = "机场快线加幅策略")
public class AirportExpressIncreaseStrategyController extends BaseController {
    @DubboReference
    private IAirportExpressIncreaseStrategyService airportExpressIncreaseStrategyService;

    @ApiOperation(value = "机场快线加幅策略-保存加幅策略", notes = "机场快线加幅策略-保存加幅策略")
    @OperationLogAnnotation(operModul = OperationLogModel.TICKET, operType = OperationLogType.ADD, operTitle = "机场快线加幅策略-保存加幅策略", operDesc = "机场快线加幅策略-保存加幅策略")
    @PostMapping("/save")
    public Result save(@RequestBody @Valid ProductIncreaseStrategyBatchReq productIncreaseStrategyBatchReq) {
        Long userId = getCurrentUser(getRequest()).getId();
        log.info("【机场快线加幅策略-保存加幅策略】data:{}", JSON.toJSONString(productIncreaseStrategyBatchReq));
        // convertor
        AirportExpressIncreaseStrategySaveBatchReq airportExpressIncreaseStrategySaveBatchReq = Convertor.scenicToAirportExpress(productIncreaseStrategyBatchReq);
        // validate
        validate(airportExpressIncreaseStrategySaveBatchReq);
        Result checkResult = checkStrategyDateResult(airportExpressIncreaseStrategySaveBatchReq.getAirportExpressIncreaseStrategyList(), true);
        if (!checkResult.isSuccess()) {
            return checkResult;
        }
        return airportExpressIncreaseStrategyService.save(airportExpressIncreaseStrategySaveBatchReq, userId);
    }

    @ApiOperation(value = "机场快线加幅策略-批量保存加幅策略", notes = "机场快线加幅策略-批量保存加幅策略")
    @OperationLogAnnotation(operModul = OperationLogModel.TICKET, operType = OperationLogType.ADD, operTitle = "机场快线加幅策略-批量保存加幅策略", operDesc = "机场快线加幅策略-批量保存加幅策略")
    @PostMapping("/save/batch")
    public Result saveBatch(@RequestBody @Valid ProductIncreaseStrategyBatchReq productIncreaseStrategyBatchReq) {
        Long userId = getCurrentUser(getRequest()).getId();
        log.info("【机场快线加幅策略-批量保存加幅策略】data:{}", JSON.toJSONString(productIncreaseStrategyBatchReq));
        // convertor
        AirportExpressIncreaseStrategySaveBatchReq airportExpressIncreaseStrategySaveBatchReq = Convertor.scenicToAirportExpress(productIncreaseStrategyBatchReq);
        // validate
        validate(airportExpressIncreaseStrategySaveBatchReq);
        Result checkResult = checkStrategyDateResult(airportExpressIncreaseStrategySaveBatchReq.getAirportExpressIncreaseStrategyList(), true);
        if (!checkResult.isSuccess()) {
            return checkResult;
        }
        return airportExpressIncreaseStrategyService.saveBatch(airportExpressIncreaseStrategySaveBatchReq, userId);
    }

    @ApiOperation(value = "机场快线加幅策略-根据机场快线ID获取加幅策略", notes = "机场快线加幅策略-根据机场快线ID获取加幅策略")
    @OperationLogAnnotation(operModul = OperationLogModel.TICKET, operType = OperationLogType.QUERY, operTitle = "机场快线加幅策略-根据快线ID获取加幅策略", operDesc = "机场快线加幅策略-根据快线ID获取加幅策略")
    @GetMapping("/{airExpressId}")
    public Result<List<ProductIncreaseStrategyDTO>> getListByExpressId(@PathVariable("airExpressId") Long airExpressId) {
        List<AirportExpressIncreaseStrategyDTO> airportExpressIncreaseStrategyDTOList = airportExpressIncreaseStrategyService.selectAirportExpressListByExpressId(airExpressId);
        return Result.success(Convertor.airportExpressToStrategyTemp(airportExpressIncreaseStrategyDTOList));
    }

    private <T> void validate(T user) {
        Set<ConstraintViolation<T>> validateSet = Validation.buildDefaultValidatorFactory()
                .getValidator()
                .validate(user, Default.class);
        if (CollectionUtils.isNotEmpty(validateSet)) {
            String messages = validateSet.stream()
                    .map(ConstraintViolation::getMessage)
                    .reduce((m1, m2) -> m1 + ";" + m2)
                    .orElse("参数输入有误！");
            throw new BusinessException(SystemError.SYS_430, messages);
        }
    }

    /**
     * 加幅策略校验器
     *
     * @param airportExpressIncreaseStrategyReqList 机场快线列表
     * @return
     */
    private Result checkStrategyDateResult(List<AirportExpressIncreaseStrategyReq> airportExpressIncreaseStrategyReqList, boolean isSaveBatch) {
        // 四种渠道至少有一个在售校验
        boolean saleFlag = false;
        for (AirportExpressIncreaseStrategyReq increaseStrategyReq : airportExpressIncreaseStrategyReqList) {
            // 线下-自营渠道
            if (Arrays.asList(1, 2, 3).contains(increaseStrategyReq.getSelfSalePermissionType())) {
                if (increaseStrategyReq.getSelfSalePermissionType() == 2) {
                    Assert.nonNull(increaseStrategyReq.getAirportExpressIncreaseStrategySelfRule(), SystemError.AIREXPRESS_50016);
                } else if (increaseStrategyReq.getSelfSalePermissionType() == 3) {
                    Assert.notEmpty(increaseStrategyReq.getAirportExpressChannelOfflineSelfCustomList(), SystemError.AIREXPRESS_50016);

                }
                saleFlag = true;
                continue;
            }
            if (Arrays.asList(1, 2, 3).contains(increaseStrategyReq.getAgentSalePermissionType())) {
                if (increaseStrategyReq.getSelfSalePermissionType() == 2) {
                    Assert.nonNull(increaseStrategyReq.getAirportExpressIncreaseStrategySelfRule(), SystemError.AIREXPRESS_50017);
                } else if (increaseStrategyReq.getSelfSalePermissionType() == 3) {
                    Assert.nonNull(increaseStrategyReq.getAirportExpressIncreaseStrategySelfRule(), SystemError.AIREXPRESS_50017);
                }
                saleFlag = true;
                continue;
            }
            //线上-自营渠道
            if (CollectionUtils.isNotEmpty(increaseStrategyReq.getAirportExpressChannelOnlineSelfPlatformList())) {
                saleFlag = true;
                continue;
            }
            //线上-第三方渠道
            if (CollectionUtils.isNotEmpty(increaseStrategyReq.getAirportExpressChannelOnlineThirdPlatformList())) {
                saleFlag = true;
                continue;
            }
            if (!saleFlag) {
                return Result.failed(SystemError.AIREXPRESS_50003);
            }
        }
        // 时间校验
        List<List<AirportExpressIncreaseStrategyDateReq>> collect = airportExpressIncreaseStrategyReqList.stream().map(AirportExpressIncreaseStrategyReq::getAirportExpressIncreaseStrategyDateList).collect(Collectors.toList());
        List<AirportExpressIncreaseStrategyDateReq> airportExpressIncreaseStrategyDateReqList = collect.get(0);
        for (int index = 0; index < airportExpressIncreaseStrategyDateReqList.size(); index++) {
            AirportExpressIncreaseStrategyDateReq strategyDateReq = airportExpressIncreaseStrategyDateReqList.get(index);
            if (isSaveBatch && strategyDateReq.getDateBegin().isBefore(LocalDate.now())) {
                // 批量机场快线保存，开始日期不能小于当前日期校验
                return Result.failed(SystemError.AIREXPRESS_50002);
            }
            if (strategyDateReq.getDateBegin().isAfter(strategyDateReq.getDateEnd())) {
                // 开始日期必须小于结束日期校验
                return Result.failed(SystemError.AIREXPRESS_50000);
            }
            for (int j = 0; j < airportExpressIncreaseStrategyDateReqList.size(); j++) {
                if (index == j) {
                    continue;
                }
                AirportExpressIncreaseStrategyDateReq strategyDateReqTemp = airportExpressIncreaseStrategyDateReqList.get(j);
                if (DateUtil.isDateRange(strategyDateReq.getDateBegin(), strategyDateReq.getDateEnd(), strategyDateReqTemp.getDateBegin(), strategyDateReqTemp.getDateEnd())) {
                    // 当前日期与其他日期区域重叠校验
                    return Result.failed(SystemError.AIREXPRESS_50001);
                }
            }
        }
        return Result.success();
    }
}
